์ธ๋ฐํ React Context ์ฌ์ฉ์ ์ํ experimental_useContextSelector๋ฅผ ์ดํด๋ณด๊ณ , ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ์ค์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํค์ธ์.
React ์ฑ๋ฅ ๊ทน๋ํ: Context ์ต์ ํ๋ฅผ ์ํ experimental_useContextSelector ์ฌ์ธต ๋ถ์
์ญ๋์ ์ธ ์น ๊ฐ๋ฐ ์ธ๊ณ์์, ์ฑ๋ฅ์ด ์ฐ์ํ๊ณ ํ์ฅ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๊ฒ์ ๋ฌด์๋ณด๋ค ์ค์ํฉ๋๋ค. React๋ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ์ ๊ฐ๋ ฅํ ํ (hook)์ ํตํด ๊ฐ๋ฐ์๊ฐ ๋ณต์กํ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค ์ ์๋๋ก ์ง์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ณต์กํด์ง์๋ก ์ํ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ค์ํ ๊ณผ์ ๊ฐ ๋ฉ๋๋ค. ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์ผ๋ฐ์ ์ธ ์์ธ ์ค ํ๋๋ ์ปดํฌ๋ํธ๊ฐ React Context์ ๋ณ๊ฒฝ ์ฌํญ์ ์๋นํ๊ณ ๋ฐ์ํ๋ ๋ฐฉ์์์ ์ข ์ข ๋ฐ์ํฉ๋๋ค.
์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ React Context์ ๋ฏธ๋ฌํ ์ฐจ์ด์ ์ ํ๊ตฌํ๊ณ , ๊ธฐ์กด์ ์ฑ๋ฅ ํ๊ณ๋ฅผ ๋
ธ์ถํ๋ฉฐ, ํ์ ์ ์ธ ์คํ์ฉ ํ
์ธ experimental_useContextSelector๋ฅผ ์๊ฐํ ๊ฒ์
๋๋ค. ์ฐ๋ฆฌ๋ ์ด ํ์ ์ ์ธ ๊ธฐ๋ฅ์ด ์ธ๋ฐํ Context ์ ํ์ ์ํ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ ์ด๋ป๊ฒ ์ ๊ณตํ์ฌ, ๋ถํ์ํ ์ปดํฌ๋ํธ ๋ฆฌ๋ ๋๋ง์ ๊ทน์ ์ผ๋ก ์ค์ด๊ณ React ์ ํ๋ฆฌ์ผ์ด์
์์ ์๋ก์ด ์์ค์ ์ฑ๋ฅ์ ๋ฌ์ฑํ์ฌ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ๋ ๋ฐ์์ ์ด๊ณ ํจ์จ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง๋ค ์ ์๋์ง ์ดํด๋ณผ ๊ฒ์
๋๋ค.
React Context์ ๋ณดํธ์ ์ธ ์ญํ ๊ณผ ์ฑ๋ฅ ๋๋ ๋ง
React Context๋ ๋ชจ๋ ์์ค์์ ์๋์ผ๋ก props๋ฅผ ์ ๋ฌํ์ง ์๊ณ ๋ ์ปดํฌ๋ํธ ํธ๋ฆฌ๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ๊น์์ด ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ์ ์ญ ์ํ ๊ด๋ฆฌ, ์ธ์ฆ ํ ํฐ, ํ
๋ง ๊ธฐ๋ณธ ์ค์ , ์ฌ์ฉ์ ์ค์ ๋ฑ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ๋ฌ ์์ค์ ๊ฑธ์ณ ๋ง์ ์ปดํฌ๋ํธ๊ฐ ํ์๋ก ํ ์ ์๋ ๋ฐ์ดํฐ์ ๋ํ ๊ท์คํ ๋๊ตฌ์
๋๋ค. ํ
์ด์ ์ ๊ฐ๋ฐ์๋ค์ Context๋ฅผ ์๋นํ๊ธฐ ์ํด render props ๋๋ HOC(๊ณ ์ฐจ ์ปดํฌ๋ํธ)์ ์์กดํ์ง๋ง, useContext ํ
์ ๋์
์ ์ด ๊ณผ์ ์ ์๋นํ ๋จ์ํํ์ต๋๋ค.
์ฐ์ํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฝ์ง๋ง, ํ์ค useContext ํ
์๋ ํนํ ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์
์์ ๊ฐ๋ฐ์๋ฅผ ์ข
์ข
๋นํฉํ๊ฒ ๋ง๋๋ ์ค์ํ ์ฑ๋ฅ ์ฃผ์์ฌํญ์ด ๋ฐ๋ฆ
๋๋ค. ์ด ํ๊ณ๋ฅผ ์ดํดํ๋ ๊ฒ์ด React ์ ํ๋ฆฌ์ผ์ด์
์ ์ํ ๊ด๋ฆฌ๋ฅผ ์ต์ ํํ๊ธฐ ์ํ ์ฒซ ๋ฒ์งธ ๋จ๊ณ์
๋๋ค.
ํ์ค useContext๊ฐ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ์ ๋ฐํ๋ ๋ฐฉ์
useContext์ ํต์ฌ ๋ฌธ์ ๋ ์
๋ฐ์ดํธ์ ๋ํ ์ค๊ณ ์ฒ ํ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ๊ฐ useContext(MyContext)๋ฅผ ์ฌ์ฉํ์ฌ Context๋ฅผ ์๋นํ ๋, ํด๋น Context๊ฐ ์ ๊ณตํ๋ ์ ์ฒด ๊ฐ์ ๊ตฌ๋
ํฉ๋๋ค. ์ด๋ Context ๊ฐ์ ์ด๋ค ๋ถ๋ถ์ด๋ผ๋ ๋ณ๊ฒฝ๋๋ฉด React๋ ํด๋น Context๋ฅผ ์๋นํ๋ ๋ชจ๋ ์ปดํฌ๋ํธ์ ๋ฆฌ๋ ๋๋ง์ ํธ๋ฆฌ๊ฑฐํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์ด ๋์์ ์๋๋ ๊ฒ์ด๋ฉฐ, ๊ฐ๋จํ๊ณ ์์ฃผ ๋ฐ์ํ์ง ์๋ ์
๋ฐ์ดํธ์๋ ์ข
์ข
๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ณต์กํ ์ ์ญ ์ํ ๋๋ ์์ฃผ ์
๋ฐ์ดํธ๋๋ Context ๊ฐ์ ๊ฐ์ง ์ ํ๋ฆฌ์ผ์ด์
์์๋ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ด ์ฐ์์ ์ผ๋ก ๋ฐ์ํ์ฌ ์ฑ๋ฅ์ ์๋นํ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค.
Context์ ์ฌ์ฉ์ ์ ๋ณด, ์ ํ๋ฆฌ์ผ์ด์ ์ค์ , ์๋ฆผ ๋ฑ ์ฌ๋ฌ ์์ฑ์ ๊ฐ์ง ํฐ ๊ฐ์ฒด๊ฐ ์๋ ์๋๋ฆฌ์ค๋ฅผ ์์ํด ๋ณด์ธ์. ์ปดํฌ๋ํธ๋ ์ฌ์ฉ์์ ์ด๋ฆ์๋ง ๊ด์ฌ์ ๊ฐ์ง ์ ์์ง๋ง, ์๋ฆผ ์๊ฐ ์ ๋ฐ์ดํธ๋๋ฉด ์ ์ฒด Context ๊ฐ์ฒด๊ฐ ๋ณ๊ฒฝ๋์๊ธฐ ๋๋ฌธ์ ํด๋น ์ปดํฌ๋ํธ๋ ์ฌ์ ํ ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค. ์ด๋ ์ปดํฌ๋ํธ์ UI ์ถ๋ ฅ์ด ์๋ฆผ ์์ ๋ฐ๋ผ ์ค์ ๋ก ๋ณ๊ฒฝ๋์ง ์์ผ๋ฏ๋ก ๋นํจ์จ์ ์ ๋๋ค.
์์: ์ ์ญ ์ํ ์ ์ฅ์
์ฌ์ฉ์ ๋ฐ ํ ๋ง ์ค์ ์ ์ํ ๊ฐ๋จํ ์ ํ๋ฆฌ์ผ์ด์ Context๋ฅผ ๊ณ ๋ คํด ๋ณด์ธ์:
const AppContext = React.createContext({});
function AppProvider({ children }) {
const [state, setState] = React.useState({
user: { id: '1', name: 'Alice', email: 'alice@example.com' },
theme: 'light',
notifications: { count: 0, messages: [] }
});
const updateUserName = (newName) => {
setState(prev => ({
...prev,
user: { ...prev.user, name: newName }
}));
};
const incrementNotificationCount = () => {
setState(prev => ({
...prev,
notifications: { ...prev.notifications, count: prev.notifications.count + 1 }
}));
};
const contextValue = React.useMemo(() => ({
state,
updateUserName,
incrementNotificationCount
}), [state]);
return <AppContext.Provider value={contextValue}>{children}</AppContext.Provider>;
}
// A component that only needs the user's name
function UserNameDisplay() {
const { state } = React.useContext(AppContext);
console.log('UserNameDisplay rerendered'); // This logs even if only notifications change
return <p>User Name: {state.user.name}</p>;
}
// A component that only needs the notification count
function NotificationCount() {
const { state } = React.useContext(AppContext);
console.log('NotificationCount rerendered'); // This logs even if only user name changes
return <p>Notifications: {state.notifications.count}</p>;
}
// Parent component to trigger updates
function App() {
const { updateUserName, incrementNotificationCount } = React.useContext(AppContext);
return (
<div>
<UserNameDisplay />
<NotificationCount />
<button onClick={() => updateUserName('Bob')}>Change User Name</button>
<button onClick={incrementNotificationCount}>New Notification</button>
</div>
);
}
์ ์์์์ "์ ์๋ฆผ"์ ํด๋ฆญํ๋ฉด UserNameDisplay๊ฐ ์๋ฆผ ์์ ์์กดํ์ง ์์์๋ ๋ถ๊ตฌํ๊ณ UserNameDisplay์ NotificationCount ๋ชจ๋ ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค. ์ด๋ ์ธ๋ถํ๋์ง ์์ Context ์๋น๋ก ์ธํด ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ๋ ์ ํ์ ์ธ ์ฌ๋ก์ด๋ฉฐ, ๊ณ์ฐ ๋ฆฌ์์ค ๋ญ๋น๋ก ์ด์ด์ง๋๋ค.
experimental_useContextSelector ์๊ฐ: ๋ฆฌ๋ ๋๋ง ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ
useContext์ ๊ด๋ จ๋ ๊ด๋ฒ์ํ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์ธ์ํ React ํ์ ๋ ์ต์ ํ๋ ์๋ฃจ์
์ ํ์ํด ์์ต๋๋ค. ํ์ฌ ์คํ ๋จ๊ณ์ ์๋ ๊ฐ๋ ฅํ ์ถ๊ฐ ๊ธฐ๋ฅ ์ค ํ๋๋ experimental_useContextSelector ํ
์
๋๋ค. ์ด ํ
์ ์ปดํฌ๋ํธ๊ฐ ์ค์ ๋ก ํ์ํ Context์ ํน์ ๋ถ๋ถ์๋ง ๊ตฌ๋
ํ ์ ์๋๋ก ํจ์ผ๋ก์จ Context๋ฅผ ์๋นํ๋ ๊ทผ๋ณธ์ ์ผ๋ก ๋ค๋ฅด๊ณ ํจ์ฌ ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ๋์
ํฉ๋๋ค.
useContextSelector์ ํต์ฌ ์์ด๋์ด๋ ์์ ํ ์๋ก์ด ๊ฒ์ ์๋๋๋ค. Redux(react-redux์ useSelector ํ
์ฌ์ฉ) ๋ฐ Zustand์ ๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋ณผ ์ ์๋ ์
๋ ํฐ ํจํด์์ ์๊ฐ์ ์ป์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ๊ธฐ๋ฅ์ React์ ํต์ฌ Context API์ ์ง์ ํตํฉํ๋ฉด ์ด ํน์ ๋ฌธ์ ์ ๋ํ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋์
ํ์ง ์๊ณ ๋ Context ์๋น๋ฅผ ์ต์ ํํ๊ธฐ ์ํ ์ํํ๊ณ ๊ด์ฉ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค.
useContextSelector๋ ๋ฌด์์ธ๊ฐ์?
ํต์ฌ์ ์ผ๋ก experimental_useContextSelector๋ Context ๊ฐ์ ํน์ ๋ถ๋ถ์ ์ถ์ถํ ์ ์๊ฒ ํด์ฃผ๋ React ํ
์
๋๋ค. ์ ์ฒด Context ๊ฐ์ฒด๋ฅผ ๋ฐ๋ ๋์ , ์ปดํฌ๋ํธ๊ฐ Context์ ์ด๋ ๋ถ๋ถ์ ๊ด์ฌ์ด ์๋์ง ์ ํํ ์ ์ํ๋ "์
๋ ํฐ ํจ์"๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ฒฐ์ ์ ์ผ๋ก, ์ปดํฌ๋ํธ๋ Context ๊ฐ์ ์ ํ๋ ๋ถ๋ถ์ด ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ์๋ง ๋ฆฌ๋ ๋๋ง๋๋ฉฐ, ๋ค๋ฅธ ๊ด๋ จ ์๋ ๋ถ๋ถ์ด ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ์๋ ๋ฆฌ๋ ๋๋ง๋์ง ์์ต๋๋ค.
์ด ์ธ๋ถํ๋ ๊ตฌ๋ ๋ฉ์ปค๋์ฆ์ ์ฑ๋ฅ์ ์์ด์ ํ๋๋ฅผ ๋ฐ๊พธ๋ ์์์ ๋๋ค. ์ด๋ "ํ์ํ ๊ฒ๋ง ๋ฆฌ๋ ๋๋ง"ํ๋ ์์น์ ๋ฐ๋ฅด๋ฉฐ, ํฌ๊ฑฐ๋ ์์ฃผ ์ ๋ฐ์ดํธ๋๋ Context ์ ์ฅ์๋ฅผ ๊ฐ์ง ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ ๋๋ง ์ค๋ฒํค๋๋ฅผ ํฌ๊ฒ ์ค์ ๋๋ค. ์ด๋ ์ ๋ฐํ ์ ์ด๋ฅผ ์ ๊ณตํ์ฌ, ์ปดํฌ๋ํธ๊ฐ ํน์ ๋ฐ์ดํฐ ์ข ์์ฑ์ด ์ถฉ์กฑ๋ ๋๋ง ์ ๋ฐ์ดํธ๋๋๋ก ๋ณด์ฅํ๋ฉฐ, ์ด๋ ๋ค์ํ ํ๋์จ์ด ๊ธฐ๋ฅ์ ๊ฐ์ง ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ์ ๊ทผ ๊ฐ๋ฅํ ๋ฐ์ํ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ํ์์ ์ ๋๋ค.
์๋ ๋ฐฉ์: ์ ๋ ํฐ ํจ์
experimental_useContextSelector์ ๊ตฌ๋ฌธ์ ๊ฐ๋จํฉ๋๋ค:
const selectedValue = experimental_useContextSelector(MyContext, selector);
MyContext:React.createContext()๋ก ์์ฑํ Context ๊ฐ์ฒด์ ๋๋ค. ์ด๋ค Context์ ๊ตฌ๋ ํ๋์ง ์๋ณํฉ๋๋ค.selector: ์ ์ฒด Context ๊ฐ์ ์ธ์๋ก ๋ฐ๊ณ ์ปดํฌ๋ํธ์ ํ์ํ ํน์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ ์์ ํจ์์ ๋๋ค. React๋ ๋ฆฌ๋ ๋๋ง์ด ํ์ํ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๊ธฐ ์ํด ์ด ์ ๋ ํฐ ํจ์์ ๋ฐํ ๊ฐ์ ๋ํ ์ฐธ์กฐ ๋์ผ์ฑ(===)์ ์ฌ์ฉํฉ๋๋ค.
์๋ฅผ ๋ค์ด, Context ๊ฐ์ด { user: { name: 'Alice', age: 30 }, theme: 'light' }์ด๊ณ ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉ์์ ์ด๋ฆ๋ง ํ์ํ๋ค๋ฉด, ์
๋ ํฐ ํจ์๋ (contextValue) => contextValue.user.name๊ณผ ๊ฐ์ ๊ฒ์
๋๋ค. ์ฌ์ฉ์์ ๋์ด๋ง ๋ณ๊ฒฝ๋๊ณ ์ด๋ฆ์ ๋์ผํ๊ฒ ์ ์ง๋๋ค๋ฉด, ์ ํ๋ ๊ฐ(์ด๋ฆ ๋ฌธ์์ด)์ ์ฐธ์กฐ๋ ์์ ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์์์ผ๋ฏ๋ก ์ด ์ปดํฌ๋ํธ๋ ๋ฆฌ๋ ๋๋ง๋์ง ์์ต๋๋ค.
ํ์ค useContext์์ ์ฃผ์ ์ฐจ์ด์
experimental_useContextSelector์ ํ์ ์์ ํ ์ดํดํ๋ ค๋ฉด, ๊ทธ ์ ์ ์ธ useContext์์ ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด์ ์ ๊ฐ์กฐํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค:
-
๊ตฌ๋
์ ์ธ๋ถ์ฑ:
useContext: ์ด ํ ์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ ์ ์ฒด Context ๊ฐ์ ๊ตฌ๋ ํฉ๋๋ค.Context.Provider์valueprop์ ์ ๋ฌ๋ ๊ฐ์ฒด์ ๋ํ ๋ณ๊ฒฝ ์ฌํญ์ ๋ชจ๋ ์๋น ์ปดํฌ๋ํธ์ ๋ฆฌ๋ ๋๋ง์ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค.experimental_useContextSelector: ์ด ํ ์ ์ปดํฌ๋ํธ๊ฐ ์ ๋ ํฐ ํจ์๋ฅผ ํตํด ์ ํํ Context ๊ฐ์ ํน์ ๋ถ๋ถ์๋ง ๊ตฌ๋ ํ ์ ์๋๋ก ํฉ๋๋ค. ๋ฆฌ๋ ๋๋ง์ ์ ํ๋ ๋ถ๋ถ์ด ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ์๋ง ํธ๋ฆฌ๊ฑฐ๋ฉ๋๋ค(์ฐธ์กฐ ๋์ผ์ฑ ๋๋ ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ํจ์ ๊ธฐ๋ฐ).
-
์ฑ๋ฅ ์ํฅ:
useContext: ํนํ ํฌ๊ณ ๊น๊ฒ ์ค์ฒฉ๋๊ฑฐ๋ ์์ฃผ ์ ๋ฐ์ดํธ๋๋ Context ๊ฐ์ผ๋ก ์ธํด ๊ณผ๋ํ๊ณ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ์ ๋ฐํ ์ ์์ต๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ฐ์์ฑ์ ์ ํ์ํค๊ณ ๋ฆฌ์์ค ์๋น๋ฅผ ์ฆ๊ฐ์ํฌ ์ ์์ต๋๋ค.experimental_useContextSelector: Context์ ๊ด๋ จ ์๋ ๋ถ๋ถ๋ง ๋ณ๊ฒฝ๋ ๋ ์ปดํฌ๋ํธ๊ฐ ์ ๋ฐ์ดํธ๋๋ ๊ฒ์ ๋ฐฉ์งํ์ฌ ๋ฆฌ๋ ๋๋ง์ ํฌ๊ฒ ์ค์ ๋๋ค. ์ด๋ ๋ค์ํ ์ฅ์น์์ ๋ ๋์ ์ฑ๋ฅ, ๋ ๋ถ๋๋ฌ์ด UI, ๋ ํจ์จ์ ์ธ ๋ฆฌ์์ค ํ์ฉ์ผ๋ก ์ด์ด์ง๋๋ค.
-
API ์๊ทธ๋์ฒ:
useContext(MyContext): Context ๊ฐ์ฒด๋ง ๊ฐ์ ธ์ค๊ณ ์ ์ฒด Context ๊ฐ์ ๋ฐํํฉ๋๋ค.experimental_useContextSelector(MyContext, selectorFn): Context ๊ฐ์ฒด์ ์ ๋ ํฐ ํจ์๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ ๋ ํฐ๊ฐ ์์ฑํ ๊ฐ๋ง ๋ฐํํฉ๋๋ค. ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ๋น๊ต๋ฅผ ์ํ ์ ํ์ ์ธ ๋ฒ์งธ ์ธ์๋ฅผ ๋ฐ์ ์๋ ์์ต๋๋ค.
-
"์คํ์ " ์ํ:
useContext: ์์ ์ ์ด๊ณ ํ๋ก๋์ ์ ์ค๋น๋ ํ ์ผ๋ก, ๋๋ฆฌ ์ฑํ๋๊ณ ๊ฒ์ฆ๋์์ต๋๋ค.experimental_useContextSelector: ์คํ์ฉ ํ ์ผ๋ก, ์์ง ๊ฐ๋ฐ ์ค์ด๋ฉฐ ์์ ํ๋๊ธฐ ์ ์ API ๋๋ ๋์์ด ๋ณ๊ฒฝ๋ ์ ์์์ ๋ํ๋ ๋๋ค. ์ด๋ ํ๋ก๋์ ์ฌ์ฉ์ ์ ์คํ ์ ๊ทผ ๋ฐฉ์์ ์๋ฏธํ์ง๋ง, ๋ฏธ๋ React ๊ธฐ๋ฅ ๋ฐ ์ ์ฌ์ ์ต์ ํ๋ฅผ ์ดํดํ๋ ๋ฐ ์ค์ํฉ๋๋ค.
์ด๋ฌํ ์ฐจ์ด์ ์ React์์ ๊ณต์ ์ํ๋ฅผ ์๋นํ๋ ๋ ์ง๋ฅ์ ์ด๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ๋ฐฉ์์ผ๋ก์ ์ ํ, ์ฆ ๊ด๋ฒ์ํ ๊ตฌ๋ ๋ชจ๋ธ์์ ๊ณ ๋๋ก ํ๊ฒํ ๋ ๋ชจ๋ธ๋ก์ ์ ํ์ ๊ฐ์กฐํฉ๋๋ค. ์ด๋ฌํ ์งํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋์์์ด ์ฆ๊ฐํ๋ ์์ค์ ์ํธ์์ฉ์ฑ๊ณผ ํจ์จ์ฑ์ ์๊ตฌํ๋ ํ๋ ์น ๊ฐ๋ฐ์ ์ค์ํฉ๋๋ค.
๋ ๊น์ด ํ๊ณ ๋ค๊ธฐ: ๋ฉ์ปค๋์ฆ ๋ฐ ์ด์
experimental_useContextSelector์ ๊ธฐ๋ณธ ๋ฉ์ปค๋์ฆ์ ์ดํดํ๋ ๊ฒ์ ๊ทธ ์ ์ฌ๋ ฅ์ ์ต๋ํ ํ์ฉํ๊ณ ๊ฒฌ๊ณ ํ๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ค๊ณํ๋ ๋ฐ ์ค์ํฉ๋๋ค. ์ด๋ ๋จ์ํ ๋ฌธ๋ฒ์ ์คํ ๊ทธ ์ด์์
๋๋ค. Context ์๋น์๋ฅผ ์ํ React ๋ ๋๋ง ๋ชจ๋ธ์ ๊ทผ๋ณธ์ ์ธ ํฅ์์ ๋ํ๋
๋๋ค.
์ธ๋ฐํ ๋ฆฌ๋ ๋๋ง: ํต์ฌ ์ด์
experimental_useContextSelector์ ๋ง๋ฒ์ Context ์๋น์ ์์ค์์ "์
๋ ํฐ ๊ธฐ๋ฐ ๋ฉ๋ชจ์ด์ ์ด์
" ๋๋ "์ธ๋ฐํ ์
๋ฐ์ดํธ"๋ผ๊ณ ์๋ ค์ง ๊ฒ์ ์ํํ๋ ๋ฅ๋ ฅ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ๊ฐ ์
๋ ํฐ ํจ์์ ํจ๊ป experimental_useContextSelector๋ฅผ ํธ์ถํ ๋, React๋ Provider์ ๊ฐ์ด ๋ณ๊ฒฝ๋์์ ์ ์๋ ๊ฐ ๋ ๋๋ง ์ฃผ๊ธฐ ๋์ ๋ค์ ๋จ๊ณ๋ฅผ ์ํํฉ๋๋ค:
- ์ปดํฌ๋ํธ ํธ๋ฆฌ์์ ๋ ๋์ ๊ณณ์ ์๋ ๊ฐ์ฅ ๊ฐ๊น์ด
Context.Provider๊ฐ ์ ๊ณตํ๋ ํ์ฌ Context ๊ฐ์ ์ ๊ทผํฉ๋๋ค. - ํ์ฌ Context ๊ฐ์ ์ธ์๋ก ์ฌ์ฉํ์ฌ ์ ๊ณต๋
selectorํจ์๋ฅผ ์คํํฉ๋๋ค. ์ ๋ ํฐ๋ ์ปดํฌ๋ํธ์ ํ์ํ ํน์ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํฉ๋๋ค. - ๊ทธ๋ฐ ๋ค์ ์๋ก ์ ํ๋ ๊ฐ(์
๋ ํฐ์ ๋ฐํ ๊ฐ)์ strict referential equality(
===)๋ฅผ ์ฌ์ฉํ์ฌ ์ด์ ์ ์ ํ๋ ๊ฐ๊ณผ ๋น๊ตํฉ๋๋ค. ๊ฐ์ฒด ๋๋ ๋ฐฐ์ด๊ณผ ๊ฐ์ ๋ณต์กํ ์ ํ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ ํ์ ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ํจ์๋ฅผ ์ธ ๋ฒ์งธ ์ธ์๋ก ์ ๊ณตํ ์ ์์ต๋๋ค. - ๊ฐ์ด ์๊ฒฉํ๊ฒ ๋์ผํ๊ฑฐ๋(๋๋ ์ฌ์ฉ์ ์ ์ ๋น๊ต ํจ์์ ๋ฐ๋ผ ๋์ผํ ๊ฒฝ์ฐ), React๋ ์ปดํฌ๋ํธ๊ฐ ์ค์ํ๊ฒ ์ฌ๊ธฐ๋ ํน์ ๋ฐ์ดํฐ๊ฐ ๊ฐ๋ ์ ์ผ๋ก ๋ณ๊ฒฝ๋์ง ์์๋ค๊ณ ํ๋จํฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ์ปดํฌ๋ํธ๋ ๋ฆฌ๋ ๋๋งํ ํ์๊ฐ ์์ผ๋ฉฐ, ํ ์ ์ด์ ์ ์ ํ๋ ๊ฐ์ ๋ฐํํฉ๋๋ค.
- ๊ฐ์ด ์๊ฒฉํ๊ฒ ๋์ผํ์ง ์๊ฑฐ๋ ์ปดํฌ๋ํธ์ ์ด๊ธฐ ๋ ๋๋ง์ธ ๊ฒฝ์ฐ, React๋ ์๋ก์ด ์ ํ๋ ๊ฐ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ๋ฆฌ๋ ๋๋ง์ ์์ฝํฉ๋๋ค.
์ด ์ ๊ตํ ํ๋ก์ธ์ค๋ ์ปดํฌ๋ํธ๊ฐ ๋์ผํ Context ๋ด์ ๊ด๋ จ ์๋ ๋ณ๊ฒฝ ์ฌํญ์ผ๋ก๋ถํฐ ํจ๊ณผ์ ์ผ๋ก ๋ถ๋ฆฌ๋จ์ ์๋ฏธํฉ๋๋ค. ๋๊ท๋ชจ Context ๊ฐ์ฒด์ ํ ๋ถ๋ถ์์ ๋ณ๊ฒฝ์ด ๋ฐ์ํ๋ฉด ํด๋น ํน์ ๋ถ๋ถ์ ๋ช ์์ ์ผ๋ก ์ ํํ ์ปดํฌ๋ํธ ๋๋ ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ ๋ถ๋ถ์์๋ง ๋ฆฌ๋ ๋๋ง์ด ํธ๋ฆฌ๊ฑฐ๋ฉ๋๋ค. ์ด๋ ์ค๋ณต ์์ ์ ํฌ๊ฒ ์ค์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ๋ ๋น ๋ฅด๊ณ ๋ฐ์์ ์ผ๋ก ๋๊ปด์ง๊ฒ ํฉ๋๋ค.
์ฑ๋ฅ ํฅ์: ์ค๋ฒํค๋ ๊ฐ์
experimental_useContextSelector์ ์ฆ๊ฐ์ ์ด๊ณ ๊ฐ์ฅ ์ค์ํ ์ด์ ์ ์ ํ๋ฆฌ์ผ์ด์
์ฑ๋ฅ์ ๊ฐ์์ ์ธ ํฅ์์
๋๋ค. ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ๋ฐฉ์งํจ์ผ๋ก์จ React์ ์กฐ์ ํ๋ก์ธ์ค ๋ฐ ํ์ DOM ์
๋ฐ์ดํธ์ ์์๋๋ CPU ์ฌ์ดํด์ ์ค์
๋๋ค. ์ด๋ ๋ช ๊ฐ์ง ์ค์ํ ์ด์ ์ผ๋ก ์ด์ด์ง๋๋ค:
- ๋ ๋น ๋ฅธ UI ์ ๋ฐ์ดํธ: ๊ด๋ จ ์ปดํฌ๋ํธ๋ง ์ ๋ฐ์ดํธ๋๋ฏ๋ก ์ฌ์ฉ์๋ ๋ ์ ๋์ ์ด๊ณ ๋ฐ์์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝํํ์ฌ ๋ ๋์ ํ์ง๊ณผ ๋ ๋น ๋ฅธ ์ํธ ์์ฉ์ ๋๋ ์ ์์ต๋๋ค.
- ๋ฎ์ CPU ์ฌ์ฉ๋: ์ด๋ ๋ฐฐํฐ๋ฆฌ ๊ตฌ๋ ์ฅ์น(ํด๋ํฐ, ํ๋ธ๋ฆฟ, ๋ ธํธ๋ถ)์ ์ฑ๋ฅ์ด ๋ฎ์ ๊ธฐ๊ธฐ ๋๋ ์ ํ๋ ์ปดํจํ ๋ฆฌ์์ค ํ๊ฒฝ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ๋ ์ฌ์ฉ์์๊ฒ ํนํ ์ค์ํฉ๋๋ค. CPU ๋ถํ๋ฅผ ์ค์ด๋ฉด ๋ฐฐํฐ๋ฆฌ ์๋ช ์ด ์ฐ์ฅ๋๊ณ ์ ๋ฐ์ ์ธ ์ฅ์น ์ฑ๋ฅ์ด ํฅ์๋ฉ๋๋ค.
- ๋ ๋ถ๋๋ฌ์ด ์ ๋๋ฉ์ด์ ๋ฐ ์ ํ: ๋ฆฌ๋ ๋๋ง์ด ์ ๋ค๋ ๊ฒ์ ๋ธ๋ผ์ฐ์ ์ ๋ฉ์ธ ์ค๋ ๋๊ฐ JavaScript ์คํ์ผ๋ก ๋ ์ ์ ๋์ด CSS ์ ๋๋ฉ์ด์ ๋ฐ ์ ํ์ด ๋๊น์ด๋ ์ง์ฐ ์์ด ๋ ์ ๋์ ์ผ๋ก ์คํ๋ ์ ์์์ ์๋ฏธํฉ๋๋ค.
-
๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๊ฐ์:
experimental_useContextSelector๊ฐ ์ํ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ง์ ์ ์ผ๋ก ์ค์ด์ง๋ ์์ง๋ง, ๋ฆฌ๋ ๋๋ง์ด ์ ์ผ๋ฉด ์์ฃผ ๋ค์ ์์ฑ๋๋ ์ปดํฌ๋ํธ ์ธ์คํด์ค ๋๋ ๊ฐ์ DOM ๋ ธ๋์์ ๋ฐ์ํ๋ ๊ฐ๋น์ง ์ปฌ๋ ์ ์๋ ฅ์ด ์ค์ด๋ค์ด ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ ์์ ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ํ๋กํ์ ๊ธฐ์ฌํ ์ ์์ต๋๋ค. - ํ์ฅ์ฑ: ๋ณต์กํ ์ํ ํธ๋ฆฌ, ๋น๋ฒํ ์ ๋ฐ์ดํธ(์: ์ค์๊ฐ ๋ฐ์ดํฐ ํผ๋, ๋ํํ ๋์๋ณด๋), ๋๋ Context๋ฅผ ์๋นํ๋ ์ปดํฌ๋ํธ ์๊ฐ ๋ง์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ ์ฑ๋ฅ ํฅ์์ด ์๋นํ ์ ์์ต๋๋ค. ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ํ์ํค์ง ์๊ณ ์ฆ๊ฐํ๋ ๊ธฐ๋ฅ๊ณผ ์ฌ์ฉ์ ๊ธฐ๋ฐ์ ์ฒ๋ฆฌํ ์ ์๋๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ๋์ฑ ํ์ฅ ๊ฐ๋ฅํ๊ฒ ๋ง๋ญ๋๋ค.
์ด๋ฌํ ์ฑ๋ฅ ํฅ์์ ๊ณ ์ฑ๋ฅ ์ํฌ์คํ ์ด์ ์์ ๊ด์ฌ์ ์ธํฐ๋ท์ ์ฌ์ฉํ๋ ์ฌ์ฉ์๋ถํฐ ๋ชจ๋ฐ์ผ ๋ฐ์ดํฐ ์๋๊ฐ ๋๋ฆฐ ์ง์ญ์ ๋ณด๊ธํ ์ค๋งํธํฐ ์ฌ์ฉ์๊น์ง, ๋ค์ํ ์ฅ์น ๋ฐ ๋คํธ์ํฌ ์กฐ๊ฑด์์ ์ต์ข ์ฌ์ฉ์๊ฐ ์ง์ ์ฒด๊ฐํ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ง์ ์ผ๋ก ์ ์ธ๊ณ์ ์ผ๋ก ์ ๊ทผ ๊ฐ๋ฅํ๊ณ ์ฆ๊ฒ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
ํฅ์๋ ๊ฐ๋ฐ์ ๊ฒฝํ ๋ฐ ์ ์ง๋ณด์์ฑ
์์ ์ฑ๋ฅ ์ธ์๋ experimental_useContextSelector๋ React ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐ์ ๊ฒฝํ๊ณผ ์ฅ๊ธฐ์ ์ธ ์ ์ง๋ณด์์ฑ์๋ ๊ธ์ ์ ์ผ๋ก ๊ธฐ์ฌํฉ๋๋ค:
- ๋ ๋ช ํํ ์ปดํฌ๋ํธ ์ข ์์ฑ: ์ ๋ ํฐ๋ฅผ ํตํด ์ปดํฌ๋ํธ๊ฐ Context์์ ๋ฌด์์ ํ์๋ก ํ๋์ง ๋ช ์์ ์ผ๋ก ์ ์ํจ์ผ๋ก์จ ์ปดํฌ๋ํธ์ ์ข ์์ฑ์ด ํจ์ฌ ๋ ๋ช ํํด์ง๊ณ ๋ช ์์ ์ด ๋ฉ๋๋ค. ์ด๋ ๊ฐ๋ ์ฑ์ ํฅ์์ํค๊ณ , ์ฝ๋ ๊ฒํ ๋ฅผ ๋จ์ํํ๋ฉฐ, ์๋ก์ด ํ์์ด ์ ์ฒด Context ๊ฐ์ฒด๋ฅผ ์ถ์ ํ ํ์ ์์ด ์ปดํฌ๋ํธ๊ฐ ์ด๋ค ๋ฐ์ดํฐ์ ์์กดํ๋์ง ์ฝ๊ฒ ์จ๋ณด๋ฉํ๊ณ ์ดํดํ ์ ์๋๋ก ํฉ๋๋ค.
- ๋ ์ฌ์ด ๋๋ฒ๊น : ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ๋ฉด ์ ํํ ์ ๋ฐ์ํ๋์ง ์ ์ ์์ต๋๋ค: Context์ ์ ํ๋ ๋ถ๋ถ์ด ๋ณ๊ฒฝ๋์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ ํฌ๊ณ ์ผ๋ฐ์ ์ธ Context ๊ฐ์ฒด์ ๋ํ ๊ฐ์ ์ ์ด๊ณ ๋ถํน์ ํ ์ข ์์ฑ์ผ๋ก ์ธํด ์ด๋ค ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋๋์ง ์ถ์ ํ๋ ค๊ณ ํ๋ ๊ฒ๋ณด๋ค Context์ ๊ด๋ จ๋ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๋๋ฒ๊น ํ๋ ๊ฒ์ ํจ์ฌ ๊ฐ๋จํ๊ฒ ๋ง๋ญ๋๋ค. ์์ธ๊ณผ ๊ฒฐ๊ณผ ๊ด๊ณ๊ฐ ๋ ์ง์ ์ ์ ๋๋ค.
- ๋ ๋์ ์ฝ๋ ๊ตฌ์ฑ: Context ์ค๊ณ์ ๋ํ ๋ ๋ชจ๋ํ๋๊ณ ์กฐ์ง์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์ฅ๋ คํฉ๋๋ค. Context๋ฅผ ๋ถํ ํ๋๋ก ๊ฐ์ํ์ง๋ ์์ง๋ง(๋ฌผ๋ก ์ข์ ๊ดํ์ผ๋ก ๋จ์์์ง๋ง), ์ปดํฌ๋ํธ๊ฐ ํ์ํ ๊ฒ๋ง ๊ฐ์ ธ์ค๋๋ก ํจ์ผ๋ก์จ ๋๊ท๋ชจ Context๋ฅผ ๋ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์๊ฒ ํ์ฌ ๋ ์ง์ค์ ์ด๊ณ ๋ ์ฝํ ์ปดํฌ๋ํธ ๋ก์ง์ผ๋ก ์ด์ด์ง๋๋ค.
- Prop Drilling ๊ฐ์: Context API์ ํต์ฌ ์ด์ ์ธ "prop drilling"(์ง์ ์ฌ์ฉํ์ง ์๋ ์ฌ๋ฌ ๊ณ์ธต์ ์ปดํฌ๋ํธ๋ฅผ ํตํด props๋ฅผ ์ ๋ฌํ๋ ์ง๋ฃจํ๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ํ๋ก์ธ์ค)์ ํผํ๋ฉด์๋ ์ฃผ์ ์ฑ๋ฅ ๋จ์ ์ ์ํํฉ๋๋ค. ์ด๋ ๊ฐ๋ฐ์๊ฐ ๊ด๋ จ๋ ์ฑ๋ฅ ๋ถ์ ์์ด Context์ ํธ๋ฆฌํจ์ ๊ณ์ ๋๋ฆด ์ ์์์ ์๋ฏธํ๋ฉฐ, ๋ ์์ฐ์ ์ธ ๊ฐ๋ฐ ์ฃผ๊ธฐ๋ฅผ ์ด์งํฉ๋๋ค.
์ค์ฉ์ ์ธ ๊ตฌํ: ๋จ๊ณ๋ณ ๊ฐ์ด๋
๋ถํ์ํ ๋ฆฌ๋ ๋๋ง ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด experimental_useContextSelector๋ฅผ ์ด๋ป๊ฒ ์ ์ฉํ ์ ์๋์ง ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ์ด์ ์์๋ฅผ ๋ฆฌํฉํ ๋งํด ๋ด
์๋ค. ์ด๋ ์ปดํฌ๋ํธ ๋์์ ๊ฐ์์ ์ธ ์ฐจ์ด๋ฅผ ๋ณด์ฌ์ค ๊ฒ์
๋๋ค. ๊ฐ๋ฐ์ ์ํด ์ด ์คํ์ฉ ํ
์ด ํฌํจ๋ React ๋ฒ์ (React 18 ์ด์)์ ์ฌ์ฉํ๊ณ ์๋์ง ํ์ธํ์ธ์. 'react'์์ ํน๋ณํ ๊ฐ์ ธ์์ผ ํ ์๋ ์์ต๋๋ค.
import React, { useState, useMemo, createContext, experimental_useContextSelector as useContextSelector } from 'react';
์ฐธ๊ณ : ํ๋ก๋์
ํ๊ฒฝ์์ ์คํ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ์ API๊ฐ ๋ณ๊ฒฝ๋ ์ ์์ผ๋ฏ๋ก ์ ์คํ ๊ณ ๋ ค๊ฐ ํ์ํฉ๋๋ค. ์ด ์์์์๋ ๊ฐ๊ฒฐ์ฑ๊ณผ ๊ฐ๋
์ฑ์ ์ํด useContextSelector๋ผ๋ ๋ณ์นญ์ ์ฌ์ฉํฉ๋๋ค.
createContext๋ฅผ ์ฌ์ฉํ์ฌ Context ์ค์
Context ์์ฑ์ ํ์ค useContext์ ๊ฑฐ์ ๋์ผํ๊ฒ ์ ์ง๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ React.createContext๋ฅผ ์ฌ์ฉํ์ฌ Context๋ฅผ ์ ์ํ ๊ฒ์
๋๋ค. Provider ์ปดํฌ๋ํธ๋ ์ฌ์ ํ useState(๋๋ ๋ ๋ณต์กํ ๋ก์ง์ ์ํด useReducer)๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ญ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ , ์ ์ฒด ์ํ์ ์
๋ฐ์ดํธ ํจ์๋ฅผ ๊ทธ ๊ฐ์ผ๋ก ์ ๊ณตํ ๊ฒ์
๋๋ค.
// Create the context object
const AppContext = createContext({});
// The Provider component that holds and updates the global state
function AppProvider({ children }) {
const [state, setState] = useState({
user: { id: '1', name: 'Alice', email: 'alice@example.com' },
theme: 'light',
notifications: { count: 0, messages: [] }
});
// Action to update user's name
const updateUserName = (newName) => {
setState(prev => ({
...prev,
user: { ...prev.user, name: newName }
}));
};
// Action to increment notification count
const incrementNotificationCount = () => {
setState(prev => ({
...prev,
notifications: { ...prev.notifications, count: prev.notifications.count + 1 }
}));
};
// Memoize the context value to prevent unnecessary rerenders of AppProvider's direct children
// or components still using standard useContext if the context value's reference changes unnecessarily.
// This is good practice even with useContextSelector for consumers.
const contextValue = useMemo(() => ({
state,
updateUserName,
incrementNotificationCount
}), [state]); // Dependency on 'state' ensures updates when the state object itself changes
return <AppContext.Provider value={contextValue}>{children}</AppContext.Provider>;
}
contextValue์ useMemo๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ค์ํ ์ต์ ํ์
๋๋ค. AppProvider๊ฐ ๋ ๋๋ง๋ ๋๋ง๋ค(๋ด๋ถ ์์ฑ์ด ์๊ฒ ๋์ผํ๋๋ผ๋) contextValue ๊ฐ์ฒด ์์ฒด๊ฐ ์ฐธ์กฐ์ ์ผ๋ก ๋ณ๊ฒฝ๋๋ฉด *๋ชจ๋ * useContext๋ฅผ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๊ฐ ๋ถํ์ํ๊ฒ ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค. useContextSelector๊ฐ ์๋น์์๊ฒ ์ด๋ฅผ ํฌ๊ฒ ์ํํ๋๋ผ๋, Provider๊ฐ ๊ฐ๋ฅํ ํ ์์ ์ ์ธ Context ๊ฐ ์ฐธ์กฐ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ์ฌ์ ํ ์ข์ ๊ดํ์
๋๋ค. ํนํ Context์ ์์ฃผ ๋ณ๊ฒฝ๋์ง ์๋ ํจ์๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ ๋์ฑ ๊ทธ๋ ์ต๋๋ค.
experimental_useContextSelector๋ก Context ์๋น
์ด์ ์๋ก์ด ํ ์ ํ์ฉํ๋๋ก ์๋น์ ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌํฉํ ๋งํด ๋ด ์๋ค. ๊ฐ ์ปดํฌ๋ํธ์ ํ์ํ ๊ฒ์ ์ ํํ ์ถ์ถํ๋ ์ ๋ฐํ ์ ๋ ํฐ ํจ์๋ฅผ ์ ์ํ์ฌ, ์ปดํฌ๋ํธ๊ฐ ํน์ ๋ฐ์ดํฐ ์ข ์์ฑ์ด ์ถฉ์กฑ๋ ๋๋ง ๋ฆฌ๋ ๋๋ง๋๋๋ก ๋ณด์ฅํ ๊ฒ์ ๋๋ค.
// A component that only needs the user's name
function UserNameDisplay() {
// Selector function: (context) => context.state.user.name
// This component will only rerender if the 'name' property changes.
const userName = useContextSelector(AppContext, (context) => context.state.user.name);
console.log('UserNameDisplay rerendered'); // This will now only log if userName changes
return <p>User Name: {userName}</p>;
}
// A component that only needs the notification count
function NotificationCount() {
// Selector function: (context) => context.state.notifications.count
// This component will only rerender if the 'count' property changes.
const notificationCount = useContextSelector(AppContext, (context) => context.state.notifications.count);
console.log('NotificationCount rerendered'); // This will now only log if notificationCount changes
return <p>Notifications: {notificationCount}</p>;
}
// A component to trigger updates (actions) from the context.
// We use useContextSelector to get a stable reference to the functions.
function AppControls() {
const updateUserName = useContextSelector(AppContext, (context) => context.updateUserName);
const incrementNotificationCount = useContextSelector(AppContext, (context) => context.incrementNotificationCount);
return (
<div>
<button onClick={() => updateUserName('Bob')}>Change User Name</button>
<button onClick={incrementNotificationCount}>New Notification</button>
</div>
);
}
// Main application content component
function AppContent() {
return (
<div>
<UserNameDisplay />
<NotificationCount />
<AppControls />
</div>
);
}
// Root component wrapping everything in the provider
function App() {
return (
<AppProvider>
<AppContent />
</AppProvider>
);
}
์ด ๋ฆฌํฉํ ๋ง์ ํตํด "์ ์๋ฆผ"์ ํด๋ฆญํ๋ฉด NotificationCount๋ง ๋ฆฌ๋ ๋๋ง์ ๊ธฐ๋กํฉ๋๋ค. UserNameDisplay๋ ์ํฅ์ ๋ฐ์ง ์๊ณ , experimental_useContextSelector๊ฐ ์ ๊ณตํ๋ ๋ฆฌ๋ ๋๋ง์ ๋ํ ์ ๋ฐํ ์ ์ด๋ฅผ ๋ณด์ฌ์ค๋๋ค. ์ด๋ฌํ ์ธ๋ถํ๋ ์ ์ด๋ ๊ณ ์ฑ๋ฅ ์ํฌ์คํ
์ด์
์์ ๋ณด๊ธํ ์ค๋งํธํฐ์ ์ด๋ฅด๋ ๋ค์ํ ์ฅ์น ๋ฐ ๋คํธ์ํฌ ์กฐ๊ฑด์์ ์ผ๊ด๋๊ฒ ์๋ํ๋ ๊ณ ๋๋ก ์ต์ ํ๋ React ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ๋๊ตฌ์
๋๋ค. ์ด๋ ๊ท์คํ ๊ณ์ฐ ๋ฆฌ์์ค๊ฐ ์ ๋์ ์ผ๋ก ํ์ํ ๊ฒฝ์ฐ์๋ง ํ์ฉ๋๋๋ก ๋ณด์ฅํ์ฌ ๋ ํจ์จ์ ์ด๊ณ ์ง์ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์
์ผ๋ก ์ด์ด์ง๋๋ค.
๊ณ ๊ธ ํจํด ๋ฐ ๊ณ ๋ ค ์ฌํญ
experimental_useContextSelector์ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ์ ๊ฐ๋จํ์ง๋ง, ์ ์ฉ์ฑ์ ๋์ฑ ํฅ์์ํค๊ณ ์ผ๋ฐ์ ์ธ ํจ์ ์ ๋ฐฉ์งํ์ฌ Context ๊ธฐ๋ฐ ์ํ ๊ด๋ฆฌ์์ ์ต๋์ ์ฑ๋ฅ์ ์ถ์ถํ ์ ์๋ ๊ณ ๊ธ ํจํด๊ณผ ๊ณ ๋ ค ์ฌํญ์ด ์์ต๋๋ค.
์
๋ ํฐ๋ฅผ ์ํ useCallback ๋ฐ useMemo๋ฅผ ์ฌ์ฉํ ๋ฉ๋ชจ์ด์ ์ด์
experimental_useContextSelector์ ์ค์ํ ํฌ์ธํธ๋ ๊ทธ ๋์ผ์ฑ ๋น๊ต์ ๋์์
๋๋ค. ์ด ํ
์ ์
๋ ํฐ ํจ์๋ฅผ ์คํํ ๋ค์ ํด๋น *๋ฐํ ๊ฐ*์ ์ด์ ์ ๋ฐํ๋ ๊ฐ๊ณผ strict referential equality(===)๋ฅผ ์ฌ์ฉํ์ฌ ๋น๊ตํฉ๋๋ค. ๋ง์ฝ ์
๋ ํฐ๊ฐ ๋งค ์คํ๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ ๋ฐฐ์ด์ ๋ฐํํ๋ค๋ฉด(์: ๋ฐ์ดํฐ ๋ณํ, ๋ชฉ๋ก ํํฐ๋ง, ๋จ์ํ ์๋ก์ด ๊ฐ์ฒด ๋ฆฌํฐ๋ด ์์ฑ), ๊ฐ๋
์ ์ธ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋๋ผ๋ ํญ์ ๋ฆฌ๋ ๋๋ง์ ์ ๋ฐํ ๊ฒ์
๋๋ค.
ํญ์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์ ๋ ํฐ์ ์:
function UserProfileSummary() {
// This selector creates a new object { name, email } on every render of UserProfileSummary
// Consequently, it will always trigger a rerender because the object reference is new.
const userDetails = useContextSelector(AppContext,
(context) => ({ name: context.state.user.name, email: context.state.user.email })
);
// ...
}
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด experimental_useContextSelector๋ react-redux์ useSelector์ ์ ์ฌํ๊ฒ ์ ํ์ ์ธ ๋ฒ์งธ ์ธ์๋ก ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ๋น๊ต ํจ์๋ฅผ ๋ฐ์ต๋๋ค. ์ด ํจ์๋ ์ด์ ๋ฐ ์๋ก์ด ์ ํ๋ ๊ฐ์ ๋ฐ์๋ค์ด๊ณ , ๊ฐ์ด ๋์ผํ๋ค๊ณ ๊ฐ์ฃผ๋๋ฉด(๋ฆฌ๋ ๋๋ง ๋ถํ์) true๋ฅผ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด false๋ฅผ ๋ฐํํฉ๋๋ค.
์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ํจ์(์: shallowEqual) ์ฌ์ฉ:
// Helper for shallow comparison (you might import from a utility library or define it)
const shallowEqual = (a, b) => {
if (a === b) return true;
if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) return false;
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
for (let i = 0; i < keysA.length; i++) {
if (a[keysA[i]] !== b[keysA[i]]) return false;
}
return true;
};
function UserProfileSummary() {
// Now, this component will only rerender if 'name' OR 'email' actually change.
const userDetails = useContextSelector(
AppContext,
(context) => ({ name: context.state.user.name, email: context.state.user.email }),
shallowEqual // Use a shallow equality comparison
);
console.log('UserProfileSummary rerendered');
return (
<div>
<p>Name: {userDetails.name}</p>
<p>Email: {userDetails.email}</p>
</div>
);
}
์
๋ ํฐ ํจ์ ์์ฒด๋ props๋ ์ํ์ ์์กดํ์ง ์๋๋ค๋ฉด ์ธ๋ผ์ธ์ผ๋ก ์ ์ํ๊ฑฐ๋ ์ปดํฌ๋ํธ ์ธ๋ถ์ ์์ ์ ์ธ ํจ์๋ก ์ถ์ถํ ์ ์์ต๋๋ค. ๊ฐ์ฅ ์ค์ํ ์ ์ *๋ฐํ ๊ฐ์ ์์ ์ฑ*์ด๋ฉฐ, ์ด๋ ๋น์์ ํ์
์ ํ์ ์์ด ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ํจ์๊ฐ ์ค์ํ ์ญํ ์ ํ๋ ๋ถ๋ถ์
๋๋ค. ์ปดํฌ๋ํธ props๋ ์ํ์ *์์กดํ๋* ์
๋ ํฐ์ ๊ฒฝ์ฐ, ํนํ ํ์ ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋๊ฑฐ๋ ์์กด์ฑ ๋ชฉ๋ก์ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ, ์
๋ ํฐ ์ ์๋ฅผ useCallback์ผ๋ก ๊ฐ์ธ์ ์์ฒด ์ฐธ์กฐ ์์ ์ฑ์ ๋ณด์ฅํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ๋จํ๊ณ ์์ฒด ํฌํจ๋ ์
๋ ํฐ์ ๊ฒฝ์ฐ, ๋ฐํ ๊ฐ์ ์์ ์ฑ์ ์ด์ ์ด ๋ง์ถฐ์ง๋๋ค.
๋ณต์กํ ์ํ ๊ตฌ์กฐ ๋ฐ ํ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
๊น๊ฒ ์ค์ฒฉ๋ ์ํ๋ ์ฌ๋ฌ Context ์์ฑ์์ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ํ์ํด์ผ ํ ๋ ์ ๋ ํฐ๋ ๋์ฑ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๋ณต์กํ ์ ๋ ํฐ๋ฅผ ๊ตฌ์ฑํ๊ฑฐ๋ ์ ํธ๋ฆฌํฐ ํจ์๋ฅผ ์์ฑํ์ฌ ๊ด๋ฆฌํจ์ผ๋ก์จ ๋ชจ๋์ฑ ๋ฐ ๊ฐ๋ ์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
// Example: A selector utility for a user's full name, assuming firstName and lastName were separate
const selectUserFullName = (context) =>
`${context.state.user.firstName || ''} ${context.state.user.lastName || ''}`.trim();
// Example: A selector for only active (unread) notifications
const selectActiveNotifications = (context) => {
const allMessages = context.state.notifications.messages;
return allMessages.filter(msg => !msg.read);
};
// In a component using these selectors:
function NotificationList() {
const activeMessages = useContextSelector(AppContext, selectActiveNotifications, shallowEqual);
// Note: shallowEqual for arrays compares array references.
// For content comparison, you might need a more robust deep equality or memoization strategy.
return (
<div>
<h3>Active Notifications</h3>
<ul>
{activeMessages.map(msg => <li key={msg.id}>{msg.text}</li>)}
</ul>
</div>
);
}
ํ์๋(๋ฐ๋ผ์ ๋ชจ๋ ์ํ ์
๋ฐ์ดํธ์์ ์๋ก์ด) ๋ฐฐ์ด์ด๋ ๊ฐ์ฒด๋ฅผ ์ ํํ ๋, useContextSelector์ ์ธ ๋ฒ์งธ ์ธ์๋ก ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ํจ์(์: shallowEqual ๋๋ ๋ณต์กํ ์ค์ฒฉ ๊ฐ์ฒด์ ํ์ํ ๊ฒฝ์ฐ `deepEqual` ํจ์)๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ์ฑ๋ฅ ์ด์ ์ ์ ์งํ๋ ๋ฐ ์ค์ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ด์ฉ์ด ๋์ผํ๋๋ผ๋ ์ ๋ฐฐ์ด/๊ฐ์ฒด ์ฐธ์กฐ๋ก ์ธํด ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ์ฌ ์ต์ ํ๊ฐ ๋ฌดํจํ๋ฉ๋๋ค.
ํผํด์ผ ํ ํจ์ : ๊ณผ๋ํ ์ ํ, ์ ๋ ํฐ ๋ถ์์ ์ฑ
-
๊ณผ๋ํ ์ ํ: ์ธ๋ถํํ๋ ๊ฒ์ด ๋ชฉํ์ด์ง๋ง, Context์์ ๋๋ฌด ๋ง์ ๊ฐ๋ณ ์์ฑ์ ์ ํํ๋ฉด ๋๋ก๋ ๋ ์ฅํฉํ ์ฝ๋์ ๊ฐ ์์ฑ์ด ๊ฐ๋ณ์ ์ผ๋ก ์ ํ๋๋ ๊ฒฝ์ฐ ์ ์ฌ์ ์ผ๋ก ๋ ๋ง์ ์
๋ ํฐ ์ฌ์คํ์ผ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๊ท ํ์ ์ ์งํ์ธ์: ์ปดํฌ๋ํธ๊ฐ ์ค์ ๋ก ํ์ํ ๊ฐ์ฅ ์์ ์ํ ์กฐ๊ฐ๋ง ์ ํํ์ธ์. ์ปดํฌ๋ํธ๊ฐ 5-10๊ฐ์ ๊ด๋ จ ์์ฑ์ ํ์๋ก ํ๋ ๊ฒฝ์ฐ, ํด๋น ์์ฑ์ ํฌํจํ๋ ์๊ณ ์์ ์ ์ธ ๊ฐ์ฒด๋ฅผ ์ ํํ๊ณ ์ฌ์ฉ์ ์ ์ ์์ ๋์ผ์ฑ ๊ฒ์ฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, ํด๋น ํน์ ์ปดํฌ๋ํธ์ ์ฑ๋ฅ ์ํฅ์ด ๋ฌด์ํ ์ ์๋ ๊ฒฝ์ฐ ๋จ์ํ ๋จ์ผ
useContextํธ์ถ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ํจ์จ์ ์ผ ์ ์์ต๋๋ค. -
๋น์ผ ์
๋ ํฐ: ์
๋ ํฐ ํจ์๋ Provider์ ๋ชจ๋ ๋ ๋๋ง์์(๋๋ Provider์ ์ ๋ฌ๋ Context ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค, ์์ ์ ์ธ ์ฐธ์กฐ์ผ์ง๋ผ๋) ์คํ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์
๋ ํฐ๊ฐ ๊ณ์ฐ์ ์ผ๋ก ์ ๋ ดํ์ง ํ์ธํ์ธ์. ์
๋ ํฐ ๋ด์์ ๋ณต์กํ ๋ฐ์ดํฐ ๋ณํ, ๊น์ ๋ณต์ฌ ๋๋ ๋คํธ์ํฌ ์์ฒญ์ ํผํ์ธ์. ์
๋ ํฐ๊ฐ ๋น์ธ๋ค๋ฉด, ํด๋น ํ์ ์ํ๋ฅผ ์ปดํฌ๋ํธ ํธ๋ฆฌ์์ ๋ ๋์ ๊ณณ์์ ๊ณ์ฐ(์:
useMemo๋ฅผ ์ฌ์ฉํ์ฌ Provider ์์ฒด ๋ด์์)ํ๊ณ , ๋ฉ๋ชจ์ด์ ์ด์ ๋ ํ์ ๊ฐ์ Context์ ์ง์ ๋ฃ๋ ๊ฒ์ด ๋ง์ ์๋น์ ์ปดํฌ๋ํธ์์ ๋ฐ๋ณต์ ์ผ๋ก ๊ณ์ฐํ๋ ๊ฒ๋ณด๋ค ๋ ๋์ ์ ์์ต๋๋ค. -
์๋์น ์์ ์ ์ฐธ์กฐ: ์์ ์ธ๊ธํ๋ฏ์ด, ์
๋ ํฐ๊ฐ ์คํ๋ ๋๋ง๋ค ๊ฐ๋
์ ์ผ๋ก ๊ธฐ๋ณธ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์ง ์์๋๋ผ๋ ํญ์ ์ ๊ฐ์ฒด๋ ๋ฐฐ์ด์ ๋ฐํํ๋ ๊ฒฝ์ฐ, ๊ธฐ๋ณธ strict equality ๊ฒ์ฌ(
===)๊ฐ ์คํจํ๋ฏ๋ก ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํฉ๋๋ค. ๋ชจ๋ ์ ๋ฐ์ดํธ์์ ์๋ก ์์ฑ๋์ง ์์์ผ ํ๋ ๊ฒฝ์ฐ, ์ ๋ ํฐ ๋ด์์ ๊ฐ์ฒด ๋ฐ ๋ฐฐ์ด ๋ฆฌํฐ๋ด ์์ฑ({},[])์ ํญ์ ์ ์ํ์ธ์. ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ํจ์๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ Provider์์ ๋ฐ์ดํฐ๊ฐ ์ง์ ์ผ๋ก ์ฐธ์กฐ์ ์ผ๋ก ์์ ์ ์ธ์ง ํ์ธํ์ธ์.
์ฌ๋ฐ๋ฅธ ์ (์์ ํ์ ์ ๊ฒฝ์ฐ):(ctx) => ctx.user.name(์์ ํ์ ์ธ ๋ฌธ์์ด์ ๋ฐํํ๋ฉฐ ์ฐธ์กฐ์ ์ผ๋ก ์์ ์ ์ ๋๋ค) ์ ์ฌ์ ๋ฌธ์ (์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ์๋ ๊ฐ์ฒด/๋ฐฐ์ด์ ๊ฒฝ์ฐ):(ctx) => ({ name: ctx.user.name, email: ctx.user.email })(์ ๋ ํฐ ์คํ๋ง๋ค ์๋ก์ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๋ฐํํ๋ฉฐ, ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ํจ์๊ฐ ์ฌ์ฉ๋์ง ์์ผ๋ฉด ํญ์ ๋ฆฌ๋ ๋๋ง์ ์ ๋ฐํฉ๋๋ค)
๋ค๋ฅธ ์ํ ๊ด๋ฆฌ ์๋ฃจ์ ๊ณผ์ ๋น๊ต
experimental_useContextSelector๋ฅผ React ์ํ ๊ด๋ฆฌ ์๋ฃจ์
์ ๋ ๋์ ๋ฒ์ ๋ด์์ ํฌ์ง์
๋ํ๋ ๊ฒ์ด ์ ์ตํฉ๋๋ค. ๊ฐ๋ ฅํ์ง๋ง ๋ง๋ฅ์ ์๋๋ฉฐ, ์ข
์ข
๋ค๋ฅธ ๋๊ตฌ ๋ฐ ํจํด์ ์์ ํ ๋์ฒดํ๊ธฐ๋ณด๋ค๋ ๋ณด์ํฉ๋๋ค.
useReducer์ useContext ์กฐํฉ
๋ง์ ๊ฐ๋ฐ์๊ฐ ๋ณต์กํ ์ํ ๋ก์ง ๋ฐ ์
๋ฐ์ดํธ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด useReducer์ useContext๋ฅผ ๊ฒฐํฉํฉ๋๋ค. useReducer๋ ์ํ ์
๋ฐ์ดํธ๋ฅผ ์ค์ ์ง์คํํ์ฌ ํนํ ์ํ ์ ํ์ด ๋ณต์กํ ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ํ
์คํธ ๊ฐ๋ฅํ๊ฒ ๋ง๋ญ๋๋ค. useReducer์ ๊ฒฐ๊ณผ ์ํ๋ Context.Provider๋ฅผ ํตํด ํ์๋ก ์ ๋ฌ๋ฉ๋๋ค. experimental_useContextSelector๋ ์ด ํจํด๊ณผ ์๋ฒฝํ๊ฒ ์ ์ด์ธ๋ฆฝ๋๋ค.
์ด๋ Provider ๋ด์์ ๊ฒฌ๊ณ ํ ์ํ ๋ก์ง์ ์ํด useReducer๋ฅผ ์ฌ์ฉํ ๋ค์, ์ปดํฌ๋ํธ์์ ํด๋น ๋ฆฌ๋์ ์ํ์ ํน์ , ์ธ๋ถํ๋ ๋ถ๋ถ์ ํจ์จ์ ์ผ๋ก ์๋นํ๊ธฐ ์ํด useContextSelector๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํฉ๋๋ค. ์ด ์กฐํฉ์ React ์์ฒด ์ธ์ ์ธ๋ถ ์์กด์ฑ ์์ด React ์ ํ๋ฆฌ์ผ์ด์
์์ ์ ์ญ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฒฌ๊ณ ํ๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ํจํด์ ์ ๊ณตํ๋ฉฐ, ํนํ ์์กด์ฑ ํธ๋ฆฌ๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ์ ์งํ๋ ค๋ ํ์๊ฒ ๋งค๋ ฅ์ ์ธ ์ ํ์ด ๋ฉ๋๋ค.
// Inside AppProvider
const [state, dispatch] = useReducer(appReducer, initialState);
const contextValue = useMemo(() => ({
state,
dispatch
}), [state, dispatch]); // Ensure dispatch is also stable, usually it is by React
// In a consumer component
const userName = useContextSelector(AppContext, (ctx) => ctx.state.user.name);
const dispatch = useContextSelector(AppContext, (ctx) => ctx.dispatch);
// Now, userName updates only when the user's name changes, and dispatch is stable.
Zustand, Jotai, Recoil๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
Zustand, Jotai, Recoil๊ณผ ๊ฐ์ ํ๋์ ์ด๊ณ ๊ฒฝ๋์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ข
์ข
์ธ๋ถํ๋ ๊ตฌ๋
๋ฉ์ปค๋์ฆ์ ํต์ฌ ๊ธฐ๋ฅ์ผ๋ก ์ ๊ณตํฉ๋๋ค. ์ด๋ค์ experimental_useContextSelector์ ์ ์ฌํ ์ฑ๋ฅ ์ด์ ์ ๋ฌ์ฑํ๋ฉฐ, ์ข
์ข
์ฝ๊ฐ ๋ค๋ฅธ API, ์ ์ ๋ชจ๋ธ(์: ์ํฐ ๊ธฐ๋ฐ ์ํ), ๊ทธ๋ฆฌ๊ณ ์ฒ ํ์ ์ ๊ทผ ๋ฐฉ์(์: ๋ถ๋ณ์ฑ ์ ํธ, ๋๊ธฐ ์
๋ฐ์ดํธ, ๋๋ ํ์ ์ํ ๋ฉ๋ชจ์ด์ ์ด์
๊ธฐ๋ณธ ์ ๊ณต)์ ๊ฐ์ง๋๋ค.
์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํน์ ์ฌ์ฉ ์ฌ๋ก์ ํ์ํ ์ ํ์ด๋ฉฐ, ํนํ ์์ํ Context API๊ฐ ์ ๊ณตํ ์ ์๋ ๊ฒ๋ณด๋ค ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ(์: ๊ณ ๊ธ ๊ณ์ฐ ์ํ, ๋น๋๊ธฐ ์ํ ๊ด๋ฆฌ ํจํด, prop drilling ๋๋ ๊ด๋ฒ์ํ Context ์ค์ ์์ด ์ํ์ ๋ํ ์ ์ญ ์ก์ธ์ค)์ด ํ์ํ ๋ ๋์ฑ ๊ทธ๋ ์ต๋๋ค. experimental_useContextSelector๋ React๊ฐ ์ธ๋ถํ๋ Context ์๋น๋ฅผ ์ํ ๊ธฐ๋ณธ ์ ๊ณต ์๋ฃจ์
์ ์ ๊ณตํ๋ ค๋ ๋จ๊ณ๋ผ๊ณ ํ ์ ์์ต๋๋ค. ์ด๋ ์ฃผ์ ๋๊ธฐ๊ฐ Context ์ฑ๋ฅ ์ต์ ํ์ธ ๊ฒฝ์ฐ ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํ ์ฆ๊ฐ์ ์ธ ํ์์ฑ์ ์ค์ผ ์ ์์ต๋๋ค.
Redux ๋ฐ useSelector ํ
๋ ํ๋ฆฝ๋๊ณ ํฌ๊ด์ ์ธ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Redux๋ ์ด๋ฏธ ์์ฒด useSelector ํ
(react-redux ๋ฐ์ธ๋ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณต)์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ์ด๋ ๋๋๋๋ก ์ ์ฌํ ์๋ฆฌ๋ก ์๋ํฉ๋๋ค. react-redux์ useSelector ํ
์ ์
๋ ํฐ ํจ์๋ฅผ ๋ฐ์๋ค์ด๊ณ , Redux ์คํ ์ด์ ์ ํ๋ ๋ถ๋ถ์ด ๋ณ๊ฒฝ๋ ๋๋ง ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋งํ๋ฉฐ, ๊ธฐ๋ณธ ์์ ๋์ผ์ฑ ๋น๊ต ๋๋ ์ฌ์ฉ์ ์ ์ ๋น๊ต๋ฅผ ํ์ฉํฉ๋๋ค. ์ด ํจํด์ ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์
์์ ์ํ ์
๋ฐ์ดํธ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐ ๋งค์ฐ ํจ๊ณผ์ ์ธ ๊ฒ์ผ๋ก ์
์ฆ๋์์ต๋๋ค.
experimental_useContextSelector์ ๊ฐ๋ฐ์ React ์ํ๊ณ์ ๋ชจ๋ฒ ์ฌ๋ก ์๋ ด์ ๋ํ๋
๋๋ค: ํจ์จ์ ์ธ ์ํ ์๋น๋ฅผ ์ํ ์
๋ ํฐ ํจํด์ Redux์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ทธ ๊ฐ์น๋ฅผ ์
์ฆํ์ผ๋ฉฐ, React๋ ์ด์ ์ด์ ๋ฒ์ ์ ํต์ฌ Context API์ ์ง์ ํตํฉํ๊ณ ์์ต๋๋ค. ์ด๋ฏธ Redux๋ฅผ ์ฌ์ฉํ๊ณ ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฒฝ์ฐ, experimental_useContextSelector๊ฐ react-redux์ useSelector๋ฅผ ๋์ฒดํ์ง๋ ์์ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ๊ธฐ๋ณธ React ๊ธฐ๋ฅ์ ๊ณ ์ํ๊ณ Redux๊ฐ ๋๋ฌด ๋
๋จ์ ์ด๊ฑฐ๋ ํ์์ ๋นํด ๋ฌด๊ฒ๋ค๊ณ ์๊ฐํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฒฝ์ฐ, experimental_useContextSelector๋ ์ธ๋ถ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํ์ง ์๊ณ ๋ Context ๊ด๋ฆฌ ์ํ์ ๋ํด ์ ์ฌํ ์ฑ๋ฅ ํน์ฑ์ ๋ฌ์ฑํ๊ธฐ ์ํ ๋งค๋ ฅ์ ์ธ ๋์์ ์ ๊ณตํฉ๋๋ค.
"์คํ์ " ๋ผ๋ฒจ: ์ฑํ์ ๋ํ ์๋ฏธ
experimental_useContextSelector์ ๋ถ์ "์คํ์ "์ด๋ผ๋ ํ๊ทธ๋ฅผ ๋ค๋ฃจ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. React ์ํ๊ณ์์ "์คํ์ "์ด๋ผ๋ ๊ฒ์ ๋จ์ํ ๋ผ๋ฒจ์ด ์๋๋๋ค. ํนํ ์ ์ธ๊ณ ์ฌ์ฉ์ ๊ธฐ๋ฐ์ ์ํด ๊ตฌ์ถํ๋ ๊ฐ๋ฐ์๊ฐ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ์๊ธฐ์ ๋ํ ์ค์ํ ํจ์๋ฅผ ์ง๋๋๋ค.
์์ ์ฑ ๋ฐ ๋ฏธ๋ ์ ๋ง
์คํ์ ๊ธฐ๋ฅ์ด๋ผ๋ ๊ฒ์ ํ๋ฐํ ๊ฐ๋ฐ ์ค์ด๋ฉฐ, ์์ ์ ์ธ ๊ณต๊ฐ API๋ก ์ถ์๋๊ธฐ ์ ์ ํด๋น API๊ฐ ํฌ๊ฒ ๋ณ๊ฒฝ๋๊ฑฐ๋ ์ฌ์ง์ด ์ ๊ฑฐ๋ ์๋ ์์์ ์๋ฏธํฉ๋๋ค. ์ฌ๊ธฐ์๋ ๋ค์์ด ํฌํจ๋ ์ ์์ต๋๋ค:
- API ํ๋ฉด ๋ณ๊ฒฝ: ํจ์ ์๊ทธ๋์ฒ, ์ธ์ ๋๋ ๋ฐํ ๊ฐ์ด ๋ณ๊ฒฝ๋์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์์ ์ฝ๋ ์์ ์ด ํ์ํ ์ ์์ต๋๋ค.
- ๋์ ๋ณ๊ฒฝ: ๋ด๋ถ ์๋ ๋ฐฉ์, ์ฑ๋ฅ ํน์ฑ ๋๋ ๋ถ์์ฉ์ด ๋ณ๊ฒฝ๋์ด ์์์น ๋ชปํ ๋์์ ์ ๋ฐํ ์ ์์ต๋๋ค.
- ์ฌ์ฉ ์ค๋จ ๋๋ ์ ๊ฑฐ: ์ด๋ฌํ ์ค๋ํ๊ณ ์ธ์ง๋ ๋ฌธ์ ์ ์ ํด๊ฒฐํ๋ ๊ธฐ๋ฅ์ ๊ฒฝ์ฐ ๊ฐ๋ฅ์ฑ์ด ๋ฎ์ง๋ง, ์คํ ๋จ๊ณ์์ ๋ ๋์ ๋์์ด ๋ํ๋๋ฉด ๋ค๋ฅธ API๋ก ์ ์ ๋๊ฑฐ๋ ๊ธฐ์กด ํ ์ ํตํฉ๋๊ฑฐ๋ ์ฌ์ง์ด ์ ๊ฑฐ๋ ๊ฐ๋ฅ์ฑ์ ํญ์ ์์ต๋๋ค.
์ด๋ฌํ ๊ฐ๋ฅ์ฑ์๋ ๋ถ๊ตฌํ๊ณ , ์ธ๋ถํ๋ Context ์ ํ์ ๊ฐ๋
์ React์ ๊ท์คํ ์ถ๊ฐ ๊ธฐ๋ฅ์ผ๋ก ๋๋ฆฌ ์ธ์๋๊ณ ์์ต๋๋ค. React ํ์ด ์ด ๊ธฐ๋ฅ์ ํ๋ฐํ ํ์ํ๊ณ ์๋ค๋ ์ฌ์ค์ Context ๊ด๋ จ ์ฑ๋ฅ ๋ฌธ์ ํด๊ฒฐ์ ๋ํ ๊ฐํ ์์ง๋ฅผ ์์ฌํ๋ฉฐ, ๋ฏธ๋์ ์์ ์ ์ธ ๋ฒ์ ์ด ๋ค๋ฅธ ์ด๋ฆ(์: useContextSelector)์ผ๋ก ๋๋ ์ธํฐํ์ด์ค์ ์ฝ๊ฐ์ ์์ ์ฌํญ๊ณผ ํจ๊ป ์ถ์๋ ๊ฐ๋ฅ์ฑ์ด ๋์์ ๋ํ๋
๋๋ค. ์ด ์ง์์ ์ธ ์ฐ๊ตฌ๋ ๊ฐ๋ฐ์ ๊ฒฝํ๊ณผ ์ ํ๋ฆฌ์ผ์ด์
์ฑ๋ฅ์ ์ง์์ ์ผ๋ก ๊ฐ์ ํ๋ ค๋ React์ ๋
ธ๋ ฅ์ ๋ณด์ฌ์ค๋๋ค.
์ธ์ ์ฌ์ฉ์ ๊ณ ๋ คํด์ผ ํ๋๊ฐ(๊ทธ๋ฆฌ๊ณ ์ธ์ ํผํด์ผ ํ๋๊ฐ)
์คํ์ ๊ธฐ๋ฅ์ ์ฑํํ ์ง ์ฌ๋ถ๋ ์ ์ฌ์ ์ธ ์ด์ ๊ณผ ์ํ์ ๊ท ํ์ ์ ์คํ๊ฒ ๊ณ ๋ คํ์ฌ ๊ฒฐ์ ํด์ผ ํฉ๋๋ค:
- ๊ฐ๋ ์ฆ๋ช ๋๋ ํ์ต ํ๋ก์ ํธ: ์ด๋ ์คํ, ํ์ต, ๋ฏธ๋ React ํจ๋ฌ๋ค์ ์ดํด๋ฅผ ์ํ ์ด์์ ์ธ ํ๊ฒฝ์ ๋๋ค. ์ด๊ณณ์์๋ ํ๋ก๋์ ์์ ์ฑ์ด๋ผ๋ ์๋ ฅ ์์ด ์ด์ ๊ณผ ํ๊ณ๋ฅผ ์์ ๋กญ๊ฒ ํ์ํ ์ ์์ต๋๋ค.
- ๋ด๋ถ ๋๊ตฌ/ํ๋กํ ํ์ : ๋ฒ์๊ฐ ํ์ ๋์ด ์๊ณ ์ ์ฒด ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์์ ํ ์ ์ดํ ์ ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ, ์ฑ๋ฅ ํฅ์์ด ์ค์ํ๊ณ ํ์ด ์ ์ฌ์ ์ธ API ๋ณ๊ฒฝ ์ฌํญ์ ์ ์ํ๊ฒ ์ ์ํ ์ค๋น๊ฐ ๋์ด ์๋ค๋ฉด ์ฌ์ฉ์ ๊ณ ๋ คํ ์ ์์ต๋๋ค. ๋ณ๊ฒฝ์ผ๋ก ์ธํ ์ํฅ์ด ์ ๊ธฐ ๋๋ฌธ์ ๋ ์คํ ๊ฐ๋ฅํ ์ต์ ์ ๋๋ค.
-
์ฑ๋ฅ ๋ณ๋ชฉ ํ์: ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์
์์ ๋ถํ์ํ Context ๋ฆฌ๋ ๋๋ง์ผ๋ก ์ง์ ์ ์ผ๋ก ๋ฐ์ํ๋ ์ฌ๊ฐํ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ํ์ธํ์ผ๋ฉฐ, ๋ค๋ฅธ ์์ ์ ์ธ ์ต์ ํ(์: Context ๋ถํ ๋๋
useMemo์ฌ์ฉ)๊ฐ ์ถฉ๋ถํ์ง ์์ ๊ฒฝ์ฐ,experimental_useContextSelector๋ฅผ ํ์ํ๋ ๊ฒ์ ๊ท์คํ ํต์ฐฐ๋ ฅ๊ณผ ์ ์ฌ์ ์ธ ๋ฏธ๋ ์ต์ ํ ๊ฒฝ๋ก๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ช ํํ ์ํ ์ธ์์ ๊ฐ์ง๊ณ ์ํํด์ผ ํฉ๋๋ค. -
ํ๋ก๋์
์ ํ๋ฆฌ์ผ์ด์
(์ฃผ์ ํ์): ์๋ฌด์ ์ค์ํ๊ณ ๋์ค์๊ฒ ๊ณต๊ฐ๋๋ ํ๋ก๋์
์ ํ๋ฆฌ์ผ์ด์
, ํนํ ์์ ์ฑ๊ณผ ์์ธก ๊ฐ๋ฅ์ฑ์ด ์ต์ฐ์ ์ธ ์ ์ธ๊ณ์ ์ผ๋ก ๋ฐฐํฌ๋๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฒฝ์ฐ, ๋ณ๊ฒฝ ์ํ์ด ๋ด์ฌ๋์ด ์์ผ๋ฏ๋ก ์คํ์ API ์ฌ์ฉ์ ํผํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ธ ๊ถ์ฅ ์ฌํญ์
๋๋ค. ๋ฏธ๋ API ๋ณ๊ฒฝ ์ฌํญ์ ์ ์ํ๋ ๋ฐ ๋๋ ์ ์ฌ์ ์ธ ์ ์ง๋ณด์ ์ค๋ฒํค๋๊ฐ ์ฆ๊ฐ์ ์ธ ์ฑ๋ฅ ์ด์ ๋ณด๋ค ํด ์ ์์ต๋๋ค. ๋์ , Context๋ฅผ ์ ์คํ๊ฒ ๋ถํ ํ๊ฑฐ๋, Context ๊ฐ์
useMemo๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, ์ ์ฌํ ์ ๋ ํฐ ๊ธฐ๋ฐ ์ต์ ํ๋ฅผ ์ ๊ณตํ๋ ์์ ์ ์ธ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํฉํ๋ ๊ฒ๊ณผ ๊ฐ์ ์์ ์ ์ด๊ณ ์ ์ฆ๋ ๋์์ ๊ณ ๋ คํ์ธ์.
์คํ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ง ์ฌ๋ถ์ ๋ํ ๊ฒฐ์ ์ ํญ์ ํ๋ก์ ํธ์ ์์ ์ฑ ์๊ตฌ ์ฌํญ, ๊ฐ๋ฐ ํ์ ๊ท๋ชจ ๋ฐ ๊ฒฝํ, ์ ์ฌ์ ์ธ ๋ณ๊ฒฝ ์ฌํญ์ ์ ์ํ ํ์ ์ญ๋์ ๊ณ ๋ คํ์ฌ ๊ฒฐ์ ํด์ผ ํฉ๋๋ค. ๋ง์ ๊ธ๋ก๋ฒ ๊ธฐ์ ๋ฐ ๊ณ ํธ๋ํฝ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ, ์์ ์ฑ๊ณผ ์ฅ๊ธฐ์ ์ธ ์ ์ง๋ณด์์ฑ์ ์ฐ์ ์ํ๋ ๊ฒ์ด ์คํ์ ๊ธฐ๋ฅ์ ์กฐ๊ธฐ ์ฑํ๋ณด๋ค ์ฐ์ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
Context ์ ํ ์ต์ ํ๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
์ค๋ experimental_useContextSelector๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ์ ํํ๋ ๊ทธ๋ ์ง ์๋ , Context ๊ด๋ฆฌ๋ฅผ ์ํ ํน์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ฑํํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์
์ ์ฑ๋ฅ๊ณผ ์ ์ง๋ณด์์ฑ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ด๋ฌํ ์์น์ ์๊ท๋ชจ ์ง์ญ ๋น์ฆ๋์ค์์ ๋๊ท๋ชจ ๊ตญ์ ํ๋ซํผ์ ์ด๋ฅด๊ธฐ๊น์ง ๋ค์ํ React ํ๋ก์ ํธ์ ๋ณดํธ์ ์ผ๋ก ์ ์ฉ ๊ฐ๋ฅํ๋ฉฐ, ๊ฒฌ๊ณ ํ๊ณ ํจ์จ์ ์ธ ์ฝ๋๋ฅผ ๋ณด์ฅํฉ๋๋ค.
์ธ๋ถํ๋ Context
๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ์ํํ๊ธฐ ์ํ ๊ฐ์ฅ ๊ฐ๋จํ๋ฉด์๋ ํจ๊ณผ์ ์ธ ์ ๋ต ์ค ํ๋๋ ํฌ๊ณ ๋จ์ผ์ ์ธ Context๋ฅผ ๋ ์๊ณ ์ธ๋ถํ๋ Context๋ก ๋ถํ ํ๋ ๊ฒ์
๋๋ค. ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์
์ํ(์ฌ์ฉ์ ์ ๋ณด, ํ
๋ง, ์๋ฆผ, ์ธ์ด ๊ธฐ๋ณธ ์ค์ ๋ฑ)๋ฅผ ํ๋์ ๊ฑฐ๋ํ AppContext์ ๋ด๋ ๋์ , UserContext, ThemeContext, NotificationsContext๋ก ๋ถ๋ฆฌํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ฉด ์ปดํฌ๋ํธ๋ ์ค์ ๋ก ํ์ํ ํน์ Context์๋ง ๊ตฌ๋
ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํ
๋ง ์ ํ๊ธฐ๋ ThemeContext๋ง ์๋นํ์ฌ ์ฌ์ฉ์์ ์๋ฆผ ์๊ฐ ์
๋ฐ์ดํธ๋ ๋ ๋ฆฌ๋ ๋๋ง๋๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. experimental_useContextSelector๊ฐ ์ฑ๋ฅ์์ ์ด์ ๋ง์ผ๋ก ์ด๋ฌํ *ํ์์ฑ*์ ์ค์ฌ์ฃผ์ง๋ง, ์ธ๋ถํ๋ Context๋ ์ฝ๋ ๊ตฌ์ฑ, ๋ชจ๋์ฑ, ๋ชฉ์ ์ ๋ช
ํ์ฑ, ๋ ์ฌ์ด ํ
์คํธ ์ธก๋ฉด์์ ์ฌ์ ํ ์๋นํ ์ด์ ์ ์ ๊ณตํ์ฌ ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์
์์ ๊ด๋ฆฌํ๊ธฐ ๋ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
์ง๋ฅ์ ์ธ ์ ๋ ํฐ ์ค๊ณ
experimental_useContextSelector๋ฅผ ์ฌ์ฉํ ๋, ์
๋ ํฐ ํจ์์ ์ค๊ณ๋ ๊ทธ ์ ์ฌ๋ ฅ์ ์ต๋ํ ๋ฐํํ๋ ๋ฐ ๊ฐ์ฅ ์ค์ํฉ๋๋ค:
- ํน์ ์ฑ์ด ํต์ฌ: ์ปดํฌ๋ํธ๊ฐ ํ์๋ก ํ๋ ๊ฐ์ฅ ์์ ์ํ ์กฐ๊ฐ์ ํญ์ ์ ํํ์ธ์. ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉ์์ ์ด๋ฆ๋ง ํ์ํ๋ ๊ฒฝ์ฐ, ์ ๋ ํฐ๋ ์ ์ฒด ์ฌ์ฉ์ ๊ฐ์ฒด๋ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ํ๊ฐ ์๋ ์ด๋ฆ๋ง ๋ฐํํด์ผ ํฉ๋๋ค.
-
ํ์ ์ํ๋ฅผ ์ ์คํ๊ฒ ์ฒ๋ฆฌ: ์
๋ ํฐ๊ฐ ํ์ ์ํ(์: ๋ชฉ๋ก ํํฐ๋ง, ์ฌ๋ฌ ์์ฑ์ ์ ๊ฐ์ฒด๋ก ๊ฒฐํฉ)๋ฅผ ๊ณ์ฐํด์ผ ํ๋ ๊ฒฝ์ฐ, ์ ๊ฐ์ฒด/๋ฐฐ์ด ์ฐธ์กฐ๊ฐ ๋ฆฌ๋ ๋๋ง์ ์ ๋ฐํ ์ ์์์ ์ ์ํ์ธ์. ํ์ ๋ฐ์ดํฐ์ *๋ด์ฉ*์ด ๋์ผํ ๋ ๋ฆฌ๋ ๋๋ง์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฌ์ฉ์ ์ ์ ๋์ผ์ฑ ๋น๊ต(์:
shallowEqual๋๋ ํ์ํ ๊ฒฝ์ฐ ๋ ๊ฐ๋ ฅํ ๊น์ ๋์ผ์ฑ)๋ฅผ ์ํ ์ ํ์ ์ธ ๋ฒ์งธ ์ธ์๋ฅผ ํ์ฉํ์ธ์. - ์์์ฑ: ์ ๋ ํฐ๋ ์์ ํจ์์ฌ์ผ ํฉ๋๋ค. ์ฆ, ๋ถ์์ฉ(์: ์ํ๋ฅผ ์ง์ ์์ ํ๊ฑฐ๋ ๋คํธ์ํฌ ์์ฒญ)์ด ์์ด์ผ ํ๋ฉฐ, ๋์ผํ ์ ๋ ฅ์ ๋ํด ํญ์ ๋์ผํ ์ถ๋ ฅ์ ๋ฐํํด์ผ ํฉ๋๋ค. ์ด ์์ธก ๊ฐ๋ฅ์ฑ์ React์ ์กฐ์ ํ๋ก์ธ์ค์ ํ์์ ์ ๋๋ค.
-
ํจ์จ์ฑ: ์
๋ ํฐ๋ฅผ ๊ณ์ฐ์ ์ผ๋ก ๊ฐ๋ณ๊ฒ ์ ์งํ์ธ์. ์
๋ ํฐ ๋ด์์ ๋ณต์กํ๊ณ ์๊ฐ์ด ๋ง์ด ์์๋๋ ๋ฐ์ดํฐ ๋ณํ์ด๋ ๋ฌด๊ฑฐ์ด ๊ณ์ฐ์ ํผํ์ธ์. ๋ฌด๊ฑฐ์ด ๊ณ์ฐ์ด ํ์ํ ๊ฒฝ์ฐ, ์ปดํฌ๋ํธ ํธ๋ฆฌ์์ ๋ ๋์ ๊ณณ(์ด์์ ์ผ๋ก๋
useMemo๋ฅผ ์ฌ์ฉํ์ฌ Context Provider ๋ด์์)์์ ์ํํ๊ณ , ๋ฉ๋ชจ์ด์ ์ด์ ๋ ํ์ ๊ฐ์ Context์ ์ง์ ์ ๋ฌํ์ธ์. ์ด๋ ์ฌ๋ฌ ์๋น์์์ ์ค๋ณต ๊ณ์ฐ์ ๋ฐฉ์งํฉ๋๋ค.
์ฑ๋ฅ ํ๋กํ์ผ๋ง ๋ฐ ๋ชจ๋ํฐ๋ง
์ ๋ ์ฑ๊ธํ๊ฒ ์ต์ ํํ์ง ๋ง์ธ์. ๋ฌธ์ ์ ๋ํ ๊ตฌ์ฒด์ ์ธ ์ฆ๊ฑฐ ์์ด ๋ณต์กํ ์ต์ ํ๋ฅผ ๋์ ํ๋ ๊ฒ์ ํํ ์ค์์ ๋๋ค. ํญ์ React ๊ฐ๋ฐ์ ๋๊ตฌ์ Profiler๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์๋ณํ์ธ์. ์ด๋ค ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋๋์ง, ๊ทธ๋ฆฌ๊ณ ๋ ์ค์ํ๊ฒ๋ *์* ๋ฆฌ๋ ๋๋ง๋๋์ง ๊ด์ฐฐํ์ธ์. ์ด ๋ฐ์ดํฐ ๊ธฐ๋ฐ ์ ๊ทผ ๋ฐฉ์์ ์ต์ ํ ๋ ธ๋ ฅ์ ๊ฐ์ฅ ํฐ ์ํฅ์ ๋ฏธ ๋ฏธ์น ๊ณณ์ ์ง์ค์์ผ ๊ฐ๋ฐ ์๊ฐ์ ์ ์ฝํ๊ณ ๋ถํ์ํ ์ฝ๋ ๋ณต์ก์ฑ์ ๋ฐฉ์งํฉ๋๋ค.
React Profiler์ ๊ฐ์ ๋๊ตฌ๋ ๋ฆฌ๋ ๋๋ง ์ฐ์, ์ปดํฌ๋ํธ ๋ ๋๋ง ์๊ฐ ๋ฑ์ ๋ช
ํํ๊ฒ ๋ณด์ฌ์ฃผ๊ณ ๋ถํ์ํ๊ฒ ๋ ๋๋ง๋๋ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์กฐํ ์ ์์ต๋๋ค. experimental_useContextSelector์ ๊ฐ์ ์๋ก์ด ํ
์ด๋ ํจํด์ ๋์
ํ๊ธฐ ์ ์, ์ด ์๋ฃจ์
์ด ์ง์ ์ ์ผ๋ก ํด๊ฒฐํ๋ ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์ค์ ๋ก ์๋์ง ํ์ธํ๊ณ ๋ณ๊ฒฝ ์ฌํญ์ ์ํฅ์ ์ธก์ ํ์ธ์.
๋ณต์ก์ฑ๊ณผ ์ฑ๋ฅ์ ๊ท ํ
์ฑ๋ฅ์ด ์ค์ํ์ง๋ง, ๊ฐ๋นํ ์ ์๋ ์ฝ๋ ๋ณต์ก์ฑ์ ๋๊ฐ๋ก ํด์๋ ์ ๋ฉ๋๋ค. ๋ชจ๋ ์ต์ ํ๋ ์ด๋ ์ ๋์ ๋ณต์ก์ฑ์ ๋๋ฐํฉ๋๋ค. experimental_useContextSelector๋ ์
๋ ํฐ ํจ์์ ์ ํ์ ๋์ผ์ฑ ๋น๊ต๋ฅผ ํตํด Context ์๋น์ ๋ํ ์๋ก์ด ๊ฐ๋
๊ณผ ์ฝ๊ฐ ๋ค๋ฅธ ์ฌ๊ณ ๋ฐฉ์์ ๋์
ํฉ๋๋ค. ๋งค์ฐ ์์ Context์ ๊ฒฝ์ฐ, ๋๋ ์ ์ฒด Context ๊ฐ์ ์ค์ ๋ก ํ์๋ก ํ๊ณ ์์ฃผ ์
๋ฐ์ดํธ๋์ง ์๋ ์ปดํฌ๋ํธ์ ๊ฒฝ์ฐ, ํ์ค useContext๊ฐ ์ฌ์ ํ ๋ ๊ฐ๋จํ๊ณ ๊ฐ๋
์ฑ์ด ์ข์ผ๋ฉฐ ์์ ํ ์ ์ ํ ์ ์์ต๋๋ค. ๋ชฉํ๋ ์ ํ๋ฆฌ์ผ์ด์
๊ณผ ํ์ ํน์ ์๊ตฌ ์ฌํญ ๋ฐ ๊ท๋ชจ์ ์ ํฉํ ์ฑ๋ฅ ์ข๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ๋ชจ๋ ์ฐ์ถํ๋ ๊ท ํ์ ๋ง์ถ๋ ๊ฒ์
๋๋ค.
๊ฒฐ๋ก : ๊ณ ์ฑ๋ฅ React ์ ํ๋ฆฌ์ผ์ด์ ์ง์
experimental_useContextSelector์ ๋์
์ React ํ์ด ํ๋ ์์ํฌ๋ฅผ ๋ฐ์ ์ํค๊ณ , ์ค์ ๊ฐ๋ฐ์ ๊ณผ์ ๋ฅผ ์ฌ์ ์ ํด๊ฒฐํ๋ฉฐ, React ์ ํ๋ฆฌ์ผ์ด์
์ ํจ์จ์ฑ์ ํฅ์์ํค๋ ค๋ ์ง์์ ์ธ ๋
ธ๋ ฅ์ ์ฆ๊ฑฐ์
๋๋ค. Context ๊ตฌ๋
์ ๋ํ ์ธ๋ถํ๋ ์ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํจ์ผ๋ก์จ, ์ด ์คํ์ฉ ํ
์ React ์ ํ๋ฆฌ์ผ์ด์
์์ ๊ฐ์ฅ ํํ ์ฑ๋ฅ ํจ์ ์ค ํ๋์ธ ๊ด๋ฒ์ํ Context ์๋น๋ก ์ธํ ๋ถํ์ํ ์ปดํฌ๋ํธ ๋ฆฌ๋ ๋๋ง์ ์ํํ๋ ๊ฐ๋ ฅํ ๋ค์ดํฐ๋ธ ์๋ฃจ์
์ ์ ๊ณตํฉ๋๋ค.
์ ์ธ๊ณ ์ฌ์ฉ์ ๊ธฐ๋ฐ์ ์ํ ๊ณ ๋๋ก ๋ฐ์์ ์ด๊ณ ํจ์จ์ ์ด๋ฉฐ ํ์ฅ ๊ฐ๋ฅํ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ๊ธฐ ์ํด ๋
ธ๋ ฅํ๋ ๊ฐ๋ฐ์์๊ฒ experimental_useContextSelector๋ฅผ ์ดํดํ๊ณ ์ ์ฌ์ ์ผ๋ก ์คํํ๋ ๊ฒ์ ๋งค์ฐ ๊ท์คํฉ๋๋ค. ์ด ํ
์ ์ปดํฌ๋ํธ๊ฐ ๊ณต์ ์ ์ญ ์ํ์ ์ํธ ์์ฉํ๋ ๋ฐฉ์์ ์ต์ ํํ๋ ์ง์ ์ ์ด๊ณ ๊ด์ฉ์ ์ธ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ์ฌ, ์ ์ธ๊ณ์ ๋ค์ํ ์ฅ์น ๋ฐ ๋คํธ์ํฌ ์กฐ๊ฑด์์ ๋ ๋ถ๋๋ฝ๊ณ ๋น ๋ฅด๋ฉฐ ์ฆ๊ฑฐ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ์ค๋๋ ์ ๊ธ๋ก๋ฒ ๋์งํธ ํ๊ฒฝ์์ ๊ฒฝ์๋ ฅ ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ ํ์์ ์
๋๋ค.
"์คํ์ " ์ํ๋ ํ๋ก๋์
๋ฐฐํฌ์ ์ ์คํ ๊ณ ๋ ค๋ฅผ ์๊ตฌํ์ง๋ง, ๊ทธ ๊ธฐ๋ณธ ์์น๊ณผ ํด๊ฒฐํ๋ ์ค์ํ ์ฑ๋ฅ ๋ฌธ์ ๋ ์ต๊ณ ์์ค์ React ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง๋๋ ๋ฐ ๊ทผ๋ณธ์ ์
๋๋ค. React ์ํ๊ณ๊ฐ ๊ณ์ ์ฑ์ํด์ง์ ๋ฐ๋ผ, experimental_useContextSelector์ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ณ ์ฑ๋ฅ์ด ๋จ์ํ ์ด๋ง์ด ์๋๋ผ ํ๋ ์์ํฌ๋ก ๊ตฌ์ถ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ณธ์ง์ ์ธ ํน์ฑ์ธ ๋ฏธ๋๋ฅผ ์ํ ๊ธธ์ ์ด์ด์ค๋๋ค. ์ด๋ฌํ ๋ฐ์ ์ ์์ฉํ๊ณ ์ ์คํ๊ฒ ์ ์ฉํจ์ผ๋ก์จ ์ ์ธ๊ณ ๊ฐ๋ฐ์๋ค์ ์์น๋ ํ๋์จ์ด ๊ธฐ๋ฅ์ ๊ด๊ณ์์ด ๋ชจ๋ ์ฌ๋์ ์ํด ๋์ฑ ๊ฒฌ๊ณ ํ๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋๋ฉฐ ์ง์ ์ผ๋ก ์ฆ๊ฑฐ์ด ๋์งํธ ๊ฒฝํ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
์ถ๊ฐ ์๋ฃ ๋ฐ ๋ฆฌ์์ค
- ๊ณต์ React ๋ฌธ์ (์์ ์ ์ธ Context API ๋ฐ ์คํ์ ๊ธฐ๋ฅ์ ๋ํ ํฅํ ์ ๋ฐ์ดํธ)
- React ๊ฐ๋ฐ์ ๋๊ตฌ (์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์ ํ๋กํ์ผ๋ง ๋ฐ ๋๋ฒ๊น ์ฉ)
useContextSelector๋ฐ ์ ์ฌ ์ ์์ ๋ํ React ์ปค๋ฎค๋ํฐ ํฌ๋ผ ๋ฐ GitHub ๋ฆฌํฌ์งํ ๋ฆฌ ํ ๋ก- ๊ณ ๊ธ React ์ฑ๋ฅ ์ต์ ํ ๊ธฐ์ ๋ฐ ํจํด์ ๋ํ ๊ธฐ์ฌ ๋ฐ ํํ ๋ฆฌ์ผ
- Zustand, Jotai, Recoil, Redux์ ๊ฐ์ ์ธ๊ธฐ ์๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฌธ์ (์ธ๋ถํ๋ ๊ตฌ๋ ๋ชจ๋ธ ๋น๊ต์ฉ)